package com.jdd.modules.parkcar.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.andyczy.java.excel.ExcelUtils;
import com.jdd.common.api.vo.Result;
import com.jdd.common.aspect.annotation.*;
import com.jdd.common.system.query.QueryGenerator;
import com.jdd.common.system.vo.LoginUser;
import com.jdd.common.util.LoginUserUtils;
import com.jdd.common.util.PlateNoCheckUtil;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.common.util.excel.entity.params.ExportParams;
import com.jdd.common.util.excel.web.entity.vo.NormalExcelConstants;
import com.jdd.common.util.excel.web.view.EasypoiSingleExcelView;
import com.jdd.modules.configcartype.entity.ConfigCarType;
import com.jdd.modules.configcartype.service.IConfigCarTypeService;
import com.jdd.modules.parkWhiteEdit.entity.ParkWhiteEditList;
import com.jdd.modules.parkWhiteEdit.service.IParkWhiteEditListService;
import com.jdd.modules.parkcar.entity.ImportResultMessage;
import com.jdd.modules.parkcar.entity.ParkCarStored;
import com.jdd.modules.parkcar.entity.StoreCar;
import com.jdd.modules.parkcar.service.IParkCarStoredService;
import com.jdd.modules.parkcar.util.ParkCarStoreUtil;
import com.jdd.modules.parkcar.util.ParkCarUtil;
import com.jdd.modules.parkcar.vo.ParkCarRechargeVO;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * @Description: 储值车信息
 * @Author: liuyaowen
 * @Date: 2021-05-24
 * @Version: V1.0
 */
@Slf4j
@Api(tags = "储值车信息")
@RestController
@RequestMapping("/parkCar/parkCarStored")
public class ParkCarStoredController {
    @Resource
    private IParkCarStoredService parkCarStoredService;
    @Resource
    private IParkWhiteEditListService parkWhiteEditListService;
    @Resource
    private IConfigCarTypeService configCarTypeService;

    @Resource
    private IConfigParkInfoService configParkInfoService;

    @Resource
    private ExecutorService executorService;

    private ParkCarStoreUtil parkCarStoreUtil;
    private ParkCarUtil parkCarUtil;

    /**
     * 分页列表查询
     *
     * @param parkCarStored
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "储值车信息-分页列表查询")
    @ApiOperation(value = "储值车信息-分页列表查询", notes = "储值车信息-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<ParkCarStored>> queryPageList(ParkCarStored parkCarStored,
                                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                      HttpServletRequest req) {
        Result<IPage<ParkCarStored>> result = new Result<IPage<ParkCarStored>>();
        QueryWrapper<ParkCarStored> queryWrapper = QueryGenerator.initQueryWrapper(parkCarStored, req.getParameterMap());
        Page<ParkCarStored> page = new Page<ParkCarStored>(pageNo, pageSize);
        IPage<ParkCarStored> pageList = parkCarStoredService.page(page, queryWrapper);
        result.setSuccess(true);
        result.setResult(pageList);
        return result;
    }

    @AutoLog(value = "储值车信息-查询储值车可预存的最大金额")
    @ApiOperation(value = "储值车信息-查询储值车可预存的最大金额", notes = "储值车信息-查询储值车可预存的最大金额")
    @RequestMapping(value = "/getMaxFee")
    public Result<?> getMaxFee() {
        parkCarStoreUtil = new ParkCarStoreUtil();
        Result result = new Result();
        try {
            result.setResult(parkCarStoreUtil.PARK_CAR_STORE_MAX_FEE);
            return result.success("获取成功");
        } catch (Exception e) {
            return Result.error("获取储值车可预存的最大金额失败");
        }
    }

    /**
     * 添加
     *
     * @param parkCarStored
     * @return
     */
    @AutoLog(value = "储值车信息-添加")
    @ApiOperation(value = "储值车信息-添加", notes = "储值车信息-添加")
    @PostMapping(value = "/add")
    @OperationLogDetail(detail = "储值车信息添加", level = LogLevelType.ONE, operationType = OperationType.INSERT, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarStored> add(@RequestBody ParkCarStored parkCarStored) {
        Result<ParkCarStored> result = new Result<ParkCarStored>();
        try {
            ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
            if (ObjectUtil.isNull(configParkInfo)) {
                return Result.error(510, "车辆信息配置为空，请检查");
            }
            // 车牌号格式检测
            if (!PlateNoCheckUtil.checkPlateNo(parkCarStored.getPlateNo())) {
                // 检测要保存的信息中的车牌号格式
                return Result.error(510, "车牌号错误");
            }
            // 查询是否有重复的储值车信息
            LambdaQueryWrapper<ParkCarStored> parkCarStoredQueryWrapper = new LambdaQueryWrapper<>();
            parkCarStoredQueryWrapper.eq(ParkCarStored::getPlateNo, parkCarStored.getPlateNo());
            List<ParkCarStored> list = parkCarStoredService.list(parkCarStoredQueryWrapper);
            if (list.size() > 0) {
                return Result.error(510, "该车牌号已被设置为储值车，无需再次添加");
            }
            // 从登录者信息中获得车场编号与车场名称
            LoginUser loginUser = LoginUserUtils.getLoginUser();
            parkCarStored.setId(SnowFlakeUtil.getId());
            parkCarStored.setParkCode(configParkInfo.getParkCode());
            parkCarStored.setParkName(configParkInfo.getParkName());
            parkCarStored.setCreateUser(loginUser.getUsername());
            log.info("添加储值车： " + loginUser.getUsername());
            // 保存储值车信息
            parkCarStoredService.save(parkCarStored);
            result.success("添加成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败");
        }
        return result;
    }

    /**
     * 编辑
     *
     * @param parkCarStored
     * @return
     */
    @AutoLog(value = "储值车信息-编辑")
    @ApiOperation(value = "储值车信息-编辑", notes = "储值车信息-编辑")
    @PutMapping(value = "/edit")
    @OperationLogDetail(detail = "储值车信息编辑", level = LogLevelType.ONE, operationType = OperationType.UPDATE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarStored> edit(@RequestBody ParkCarStored parkCarStored) {

        // 车牌号格式检测
        if (!PlateNoCheckUtil.checkPlateNo(parkCarStored.getPlateNo())) {
            // 检测要保存的信息中的车牌号格式
            return Result.error(510, "车牌号错误");
        }
        // 查询是否有重复的储值车信息
        LambdaQueryWrapper<ParkCarStored> parkCarStoredQueryWrapper = new LambdaQueryWrapper<>();
        parkCarStoredQueryWrapper.ne(ParkCarStored::getId, parkCarStored.getId());
        parkCarStoredQueryWrapper.eq(ParkCarStored::getPlateNo, parkCarStored.getPlateNo());
        List<ParkCarStored> list = parkCarStoredService.list(parkCarStoredQueryWrapper);
        if (list.size() > 0) {
            return Result.error(510, "该车牌号已被设置为储值车，无需再次添加");
        }
        Result<ParkCarStored> result = new Result<ParkCarStored>();
        ParkCarStored parkCarStoredEntity = parkCarStoredService.getById(parkCarStored.getId());
        if (parkCarStoredEntity == null) {
            result.error500("未找到对应实体");
        } else {
            boolean ok = parkCarStoredService.updateById(parkCarStored);
            //TODO 返回false说明什么？
            if (ok) {
                result.success("修改成功!");
            }
        }
        return result;
    }

    /**
     * 储值车充值
     *
     * @param parkCarRechargeVO 储值车信息VO
     * @return
     */
    @AutoLog(value = "储值车信息-储值车充值")
    @ApiOperation(value = "储值车信息-储值车充值", notes = "储值车信息-储值车充值")
    @RequestMapping(value = "/Recharge")
    @OperationLogDetail(detail = "储值车充值", level = LogLevelType.ONE, operationType = OperationType.INSERT, operationUnit = OperationUnit.UNKNOWN)
    public Result<?> recharge(@RequestBody ParkCarRechargeVO parkCarRechargeVO) {
        // 首先检测充值金额是否小于1，不满足返回
        Integer fee = parkCarRechargeVO.getFee();
        if (fee == 0) {
            return Result.error("余额无变动");
        }
        // 检测储值车充值后的余额是否大于储值车余额的最大值
        Integer rechargeAfterFee;
        parkCarStoreUtil = new ParkCarStoreUtil();
        LoginUser loginUser = LoginUserUtils.getLoginUser();
        rechargeAfterFee = parkCarRechargeVO.getPayFee() + fee;
        if (rechargeAfterFee > parkCarStoreUtil.PARK_CAR_STORE_MAX_FEE) {
            return Result.error("储值车余额最多为10000元");
        }
        if (rechargeAfterFee < 0) {
            return Result.error("余额不足");
        }
        // 如果充值时，被充值的储值车信息被删除
        ParkCarStored parkCarStored = parkCarStoredService.getById(parkCarRechargeVO.getId());
        if (parkCarStored == null) {
            return Result.error("该储值车信息不存在");
        }
        // 保存充值纪录
        ParkWhiteEditList parkWhiteEditList = new ParkWhiteEditList();
        BeanUtils.copyProperties(parkCarStored, parkWhiteEditList);
        // 雪花算法生成ID
        parkWhiteEditList.setId(SnowFlakeUtil.getId());
        // 充值/延期纪录的操作类型为充值
        parkWhiteEditList.setOptionsType(1);
        // 充值/延期纪录的操作车辆类型为储值车
        parkWhiteEditList.setLicenseType(3);
        // 充值/延期纪录保存充值前金额
        parkWhiteEditList.setBeforePayFee(parkCarStored.getPayFee());
        // 充值/延期纪录保存充值后金额
        parkWhiteEditList.setPayFee(rechargeAfterFee);
        // 充值/延期纪录更新时间
        parkWhiteEditList.setUpdateTime(new Date());
        // 充值/延期纪录操作人
        parkWhiteEditList.setUserName(loginUser.getUsername());
        // 储值车进行充值
        parkCarStored.setPayFee(rechargeAfterFee);
        try {
            parkCarStoredService.updateById(parkCarStored);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Result.error("充值失败");
        }
        try {
            parkWhiteEditListService.save(parkWhiteEditList);
            // 如果充值前的余额大于充值后的余额
            if (rechargeAfterFee < parkWhiteEditList.getBeforePayFee()) {
                return Result.ok("退款成功");
            }
            return Result.ok("充值成功");
        } catch (Exception e) {
            log.error(e.getMessage());
            return Result.error("充值纪录保存失败");
        }
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "储值车信息-通过id删除")
    @ApiOperation(value = "储值车信息-通过id删除", notes = "储值车信息-通过id删除")
    @DeleteMapping(value = "/delete")
    @OperationLogDetail(detail = "储值车通过Id删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        try {
            parkCarStoredService.removeById(id);
        } catch (Exception e) {
            log.error("删除失败", e.getMessage());
            return Result.error("删除失败!");
        }
        return Result.ok("删除成功!");
    }

    /**
     * 储值车信息核销
     */
    @AutoLog(value = "储值车信息-核销储值车信息")
    @ApiOperation(value = "储值车信息-核销储值车信息", notes = "储值车信息-核销储值车信息")
    @RequestMapping(value = "/writeOff")
    @OperationLogDetail(detail = "储值车核销信息", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<?> writeOff(@RequestBody ParkCarStored parkCarStored) {
        parkCarUtil = new ParkCarUtil();
        ParkCarStored carStored = new ParkCarStored();
        carStored = parkCarStoredService.getById(parkCarStored.getId());
        if (carStored == null) {
            return Result.error("该储值车纪录不存在");
        }
        try {
            ParkWhiteEditList parkWhiteEditList = parkCarUtil.getParkWhiteEditList(carStored);
            parkWhiteEditList.setLicenseType(3);
            parkWhiteEditList.setPayFee(0);
            parkWhiteEditList.setBeforePayFee(parkCarStored.getPayFee());
            parkWhiteEditListService.save(parkWhiteEditList);
            parkCarStoredService.removeById(parkCarStored.getId());
        } catch (Exception e) {
            return Result.error("核销失败");
        }
        return Result.ok("核销成功");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "储值车信息-批量删除")
    @ApiOperation(value = "储值车信息-批量删除", notes = "储值车信息-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    @OperationLogDetail(detail = "储值车批量删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarStored> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        Result<ParkCarStored> result = new Result<ParkCarStored>();
        if (ids == null || "".equals(ids.trim())) {
            result.error500("参数不识别！");
        } else {
            this.parkCarStoredService.removeByIds(Arrays.asList(ids.split(",")));
            result.success("删除成功!");
        }
        return result;
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "储值车信息-通过id查询")
    @ApiOperation(value = "储值车信息-通过id查询", notes = "储值车信息-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<ParkCarStored> queryById(@RequestParam(name = "id", required = true) String id) {
        Result<ParkCarStored> result = new Result<ParkCarStored>();
        ParkCarStored parkCarStored = parkCarStoredService.getById(id);
        if (parkCarStored == null) {
            result.error500("未找到对应实体");
        } else {
            result.setResult(parkCarStored);
            result.setSuccess(true);
        }
        return result;
    }

    /**
     * 储值车导出excel
     *
     * @param request
     * @param response
     * @param parkCarStored
     */
    @AutoLog(value = "储值车信息-储值车导出")
    @ApiOperation(value = "储值车信息-储值车导出", notes = "储值车信息-储值车导出")
    @RequestMapping(value = "/storeExportXls")
    public ModelAndView storeExportXls(HttpServletRequest request, HttpServletResponse response, ParkCarStored parkCarStored) {
        // Step.1 组装查询条件
        QueryWrapper<ParkCarStored> queryWrapper = QueryGenerator.initQueryWrapper(parkCarStored, request.getParameterMap());
        parkCarStoreUtil = new ParkCarStoreUtil();
        // Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "储值车列表");
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("储值车列表数据", "导出信息"));
        // 导出文件名称
        // 查询表中数据大小
        int listSize = parkCarStoredService.count(queryWrapper);
        // 定义每页数量
        int pageSize = 100;
        // 定义线程列表
        List<CompletableFuture<ModelAndView>> futureList = new ArrayList<>();
        // 循环查询，每次查询一页
        for (int pageNo = 1; pageNo <= listSize / pageSize + 1; pageNo++) {
            int number = pageNo;
            // 开启线程查询
            CompletableFuture<ModelAndView> completableFuture = CompletableFuture.supplyAsync(() -> {
                return parkCarStoreUtil.addDataToModelAndViewStoreCar(new ModelAndView(), parkCarStoredService, queryWrapper, number, pageSize);
            }, executorService);
            futureList.add(completableFuture);
        }
        // 等待每个线程结束后
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
        List<ParkCarStored> resultList = new ArrayList<>();
        futureList.forEach(a -> {
            try {
                // 将结果添加到列表中
                resultList.addAll((List<ParkCarStored>) a.join().getModel().get(NormalExcelConstants.DATA_LIST));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 将数据添加到Excel文件内
        mv.addObject(NormalExcelConstants.CLASS, ParkCarStored.class);
        mv.addObject(NormalExcelConstants.DATA_LIST, resultList);
        return mv;
    }


    /**
     * @param request
     * @param response
     * @param map
     * @return
     */
    @AutoLog(value = "储值车信息导入-导出储值车信息模板")
    @ApiOperation(value = "储值车信息导入-导出储值车信息模板", notes = "储值车信息导入-导出储值车信息模板")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls1(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {

        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "储值车信息");
        mv.addObject(NormalExcelConstants.CLASS, StoreCar.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("储值车信息", "储值车模板"));

        StoreCar storeCar = new StoreCar(null, null, null, null, null, null, null);
        List<StoreCar> list = new LinkedList<>();
        list.add(storeCar);
        mv.addObject(NormalExcelConstants.DATA_LIST, list);
        return mv;
    }

    /**
     * @return 返回当前用户所在车场的所有储值车列表
     */
    @AutoLog(value = "储值车信息-查询用户车场对应的储值车类型列表")
    @ApiOperation(value = "储值车信息-查询用户车场对应的储值车类型列表", notes = "储值车信息-查询用户车场对应的储值车类型列表")
    @GetMapping(value = "/getStoreCarTypeList")
    public Result<List<ConfigCarType>> getStoreCarTypeList() {
        Result<List<ConfigCarType>> result = new Result<>();
        LambdaQueryWrapper<ConfigCarType> configCarTypeWrapper = new LambdaQueryWrapper<>();
        configCarTypeWrapper.eq(ConfigCarType::getCarType, "2");
        List<ConfigCarType> carTypeList = configCarTypeService.list(configCarTypeWrapper);
        result.setResult(carTypeList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @return 导入结果Excel
     */
    @AutoLog(value = "储值车信息-导入")
    @ApiOperation(value = "储值车信息-导入", notes = "储值车信息-导入")
    @RequestMapping(value = "/importExcel")
    public ModelAndView importExcel(HttpServletRequest request, @RequestParam("carTypeId") String carTypeId) throws IOException {
        log.info("----储值车信息导入----");
        // 得到登录者信息，获得登录者的车场编号
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "储值车信息导入结果");
        mv.addObject(NormalExcelConstants.CLASS, ImportResultMessage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("储值车信息导入结果", "储值车信息导入结果"));

        List<ImportResultMessage> importResultMessageList = new LinkedList<>();
        ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
        if (ObjectUtil.isNull(configParkInfo)) {
            ImportResultMessage importResultMessage = new ImportResultMessage();
            importResultMessage.setMessage("储值车信息导入失败，请先配置车场信息");
            importResultMessageList.add(importResultMessage);
            mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
            return mv;
        }
        // 获得上传文件的请求
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 从请求中获得上传文件的集合
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 遍历文件集合
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获得文件
            MultipartFile file = entity.getValue();
            // 得到文件名
            String fileName = file.getOriginalFilename();
            // 设置Excel文件的标题所在行数
            HashMap<Integer, Integer> hashMapIndex = new HashMap<>(1);
            hashMapIndex.put(1, 3);
            // 设置Excel文件单页名称
            String[] sheetNames = new String[]{"储值车模板"};
            // 获得Excel文件的输入流
            InputStream inputStream = file.getInputStream();
            Workbook book = null;
            try {
                // 获得Excel文件的扩展名
                String extName = fileName.substring(fileName.lastIndexOf('.') + 1);
                if (StringUtils.equals("xls", extName)) {
                    // Excel文件为Excel2003之前的版本
                    book = new HSSFWorkbook(inputStream);
                } else if (StringUtils.equals("xlsx", extName)) {
                    // Excel文件的版本为Excel2007
                    book = new XSSFWorkbook(inputStream);
                } else {
                    log.error("无法识别的Excel文件,请下载模板文件,进行导入!");
                    mv.addObject(NormalExcelConstants.CLASS, ImportResultMessage.class);
                    ImportResultMessage importResultMessage = new ImportResultMessage();
                    importResultMessage.setMessage("无法识别的Excel文件，请下载模板文件，进行导入！");
                    importResultMessageList.add(importResultMessage);
                    mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                    return mv;
                }
                // 初始化Excel工具类
                ExcelUtils excelUtils = ExcelUtils.initialization();
                // 设置工具类读取日期数据的格式
                excelUtils.setDateFormatStr("yyyy-MM-dd HH:mm:ss");
                excelUtils.setExpectDateFormatStr("yyyy-MM-dd HH:mm:ss");
                // 读取Excel文件
                List<List<LinkedHashMap<String, String>>> list = ExcelUtils.importForExcelData(book, sheetNames, hashMapIndex, null);
                //检测导入Excel文件的大小
                Result<Object> listSizeCheckResult = importListSizeCheck(list, 2000);
                //如果检测不通过
                if (listSizeCheckResult.getCode() != 200) {
                    ImportResultMessage importResultMessage = new ImportResultMessage();
                    importResultMessage.setMessage(listSizeCheckResult.getMessage());
                    importResultMessageList.add(importResultMessage);
                    mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                    // 返回检测结果
                    return mv;
                }
                List<ParkCarStored> parkCarStoredList = new ArrayList<>();
                List<ParkCarStored> sameParkCarStoredList = new ArrayList<>();
                for (List<LinkedHashMap<String, String>> linkedHashMaps : list) {
                    importResultMessageList = getNoSameDataParkCarStored(linkedHashMaps, parkCarStoredList, sameParkCarStoredList, carTypeId, configParkInfo);
                }

                List<CompletableFuture<List<ImportResultMessage>>> futureList = new ArrayList<>();
                int pageSize = 100;
                int pageNumber = parkCarStoredList.size() / pageSize;
                for (int i = 0; i <= pageNumber; i++) {
                    int index = i;
                    if (index == pageNumber) {
                        CompletableFuture<List<ImportResultMessage>> completableFuture = CompletableFuture.supplyAsync(() -> {
                            return importParkCarStoredListByList(parkCarStoredList.subList(index * pageSize, parkCarStoredList.size()));
                        }, executorService);
                        futureList.add(completableFuture);
                    } else {
                        CompletableFuture<List<ImportResultMessage>> completableFuture = CompletableFuture.supplyAsync(() -> {
                            return importParkCarStoredListByList(parkCarStoredList.subList(index * pageSize, index * pageSize + pageSize));
                        }, executorService);
                        futureList.add(completableFuture);
                    }
                }
                // 等待每个线程结束后
                CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
                List<ImportResultMessage> resultMessages = importResultMessageList;
                futureList.forEach(a -> {
                    try {
                        // 将结果添加到列表中
                        resultMessages.addAll((List<ImportResultMessage>) a.join());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                importResultMessageList = resultMessages;
            } catch (Exception e) {
                log.error("储值车信息导入", e);
                ImportResultMessage importResultMessage = new ImportResultMessage();
                importResultMessage.setMessage("储值车信息导入失败");
                importResultMessageList.add(importResultMessage);
                mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                return mv;
            }
        }
        if (importResultMessageList.size() == 0) {
            ImportResultMessage importResultMessage = new ImportResultMessage();
            importResultMessage.setLocationX("无");
            importResultMessage.setLocationY(0);
            importResultMessage.setPlateNo("无");
            importResultMessage.setMessage("导入成功");
            importResultMessageList.add(importResultMessage);
        }
        mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
        return mv;
    }

    /**
     * 按list批量导入
     *
     * @param list 格式正确的储值车信息
     * @return 导入结果信息
     * @Author liuyaowen
     */
    private List<ImportResultMessage> importParkCarStoredListByList(List<ParkCarStored> list) {
        List<ImportResultMessage> importResultMessageList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            ParkCarStored parkCarStored = list.get(i);
            LambdaQueryWrapper<ParkCarStored> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ParkCarStored::getPlateNo, parkCarStored.getPlateNo());
            if (parkCarStoredService.count(queryWrapper) > 0) {
                ImportResultMessage message = new ImportResultMessage();
                message.setPlateNo(parkCarStored.getPlateNo());
                message.setMessage("该车牌号已被设置为储值车，请勿重复添加");
                importResultMessageList.add(message);
            } else {
                parkCarStoredService.save(parkCarStored);
            }
        }
        return importResultMessageList;
    }

    /**
     * Excel列表中数据格式自检测
     *
     * @param linkedHashMaps 导入的储值车信息列表
     * @param noSameDataList 用于存储的格式正确的，无相同数据的储值车信息
     * @param sameDatalist   用于存储拥有相同数据的储值车信息
     * @param carTypeId      储值车类型
     * @return 导入结果信息
     * @Author liuyaowen
     */
    private List<ImportResultMessage> getNoSameDataParkCarStored(List<LinkedHashMap<String, String>> linkedHashMaps, List<ParkCarStored> noSameDataList, List<ParkCarStored> sameDatalist, String carTypeId, ConfigParkInfo configParkInfo) {
        LoginUser loginUser = LoginUserUtils.getLoginUser();
        String parkCode = configParkInfo.getParkCode();
        String parkName = configParkInfo.getParkName();
        List<ImportResultMessage> list = new ArrayList<>();
        Set<String> noSameDataPlantNoList = new HashSet<>();

        for (int index = 0; index < linkedHashMaps.size(); index++) {
            ImportResultMessage message = new ImportResultMessage();
            LinkedHashMap<String, String> linkedHashMap = linkedHashMaps.get(index);
            ParkCarStored parkCarStored = new ParkCarStored();
            if (StringUtils.isBlank(linkedHashMap.get("0")) || !PlateNoCheckUtil.checkPlateNo(linkedHashMap.get("0"))) {
                // 如果车辆的车牌号为空或错误的格式，放弃此数据，立即开始导入一下条数据
                log.error("车牌号格式错误");
                log.error("parkCode:" + parkCode + ",Plant_No" + parkCarStored.getPlateNo());
                message.setPlateNo(parkCarStored.getPlateNo());
                message.setLocationX("A");
                message.setMessage("车牌号格式错误");
                list.add(message);
                continue;
            } else {
                parkCarStored.setPlateNo(linkedHashMap.get("0"));
            }
            if (StringUtils.isBlank(linkedHashMap.get("1"))) {
                // 如果车辆的用户名称为空，放弃此数据，立即开始导入一下条数据
                log.error("储值车客户姓名为空");
                log.error("park_Code:" + parkCode + ",Plant_No：" + parkCarStored.getPlateNo());
                message.setPlateNo(parkCarStored.getPlateNo());
                message.setLocationX("B");
                message.setMessage("储值车客户姓名为空");
                list.add(message);
                continue;
            } else {
                parkCarStored.setUserName(linkedHashMap.get("1"));
            }

                parkCarStored.setMobile(linkedHashMap.get("2"));

            if ("".equals(linkedHashMap.get("3")) || (linkedHashMap.get("3")) == null) {
                parkCarStored.setPayFee(0);
            } else {
                try {
                    if (Integer.parseInt(linkedHashMap.get("3")) < 0) {
                        log.info("储值车储值金额不是正整数");
                        log.info("park_Code:" + parkCode + ",Plant_No" + linkedHashMap.get("3"));
                        message.setPlateNo(parkCarStored.getPlateNo());
                        message.setLocationX("D");
                        message.setMessage("储值车储值金额不是正整数");
                        list.add(message);
                        continue;
                    } else {
                        parkCarStored.setPayFee(Integer.parseInt(linkedHashMap.get("3")));
                    }
                } catch (NumberFormatException e) {
                    log.info("储值车储值金额不是正整数");
                    log.info("park_Code:" + parkCode + ",Plant_No" + linkedHashMap.get("3"));
                    message.setPlateNo(parkCarStored.getPlateNo());
                    message.setLocationX("D");
                    message.setMessage("储值车储值金额不是正整数");
                    list.add(message);
                    continue;
                }
            }
            parkCarStored.setId(SnowFlakeUtil.getId());
            parkCarStored.setParkCode(parkCode);
            parkCarStored.setParkName(parkName);
            parkCarStored.setAddress(linkedHashMap.get("4"));
            parkCarStored.setRemark(linkedHashMap.get("5"));
            parkCarStored.setStatus("Y");
            parkCarStored.setCarTypeId(carTypeId);
            parkCarStored.setUpdateTime(new Date());
            parkCarStored.setCreateUser(loginUser.getUsername());
            if (noSameDataPlantNoList.add(parkCarStored.getPlateNo())) {
                noSameDataList.add(parkCarStored);
            } else {
                message.setPlateNo(parkCarStored.getPlateNo());
                message.setMessage("该储值车已导入一条相同车牌号的数据，请勿重复导入");
                list.add(message);
                sameDatalist.add(parkCarStored);
            }
        }
        return list;
    }

    /**
     * 检测储值车导入列表的大小
     */
    private Result<Object> importListSizeCheck(List<List<LinkedHashMap<String, String>>> list, Integer maxSize) {

        // 如果列表大小不为0
        if (list.size() != 0) {
            if (list.get(0).size() > maxSize) {
                log.error("表格中的数据最多有" + maxSize + "条");
                return Result.error("表格中的数据最多有" + maxSize + "条");
            }
            if (list.get(0).size() != 0) {
                String[] arr = new String[list.get(0).get(0).size()];
                Arrays.fill(arr, "");
                String[] arr1 = new String[list.get(0).get(0).size()];
                String[] strings = list.get(0).get(0).values().toArray(arr1);
                if (Arrays.equals(arr, strings)) {
                    log.error("文件没有数据");
                    return Result.error("文件没有数据！");
                }
            }
        } else {
            log.error("空文件");
            return Result.error("空文件");
        }
        return Result.ok();
    }
}
